ecdsa

您所在的位置:网站首页 python 密码库 ecdsa

ecdsa

2024-05-23 08:31| 来源: 网络整理| 查看: 265

纯 Python ECDSA 和 ECDH

这是一个易于使用的 ECC(椭圆曲线加密)实现,支持 ECDSA(椭圆曲线数字签名算法)、EdDSA(爱德华兹曲线数字签名算法)和 ECDH(椭圆曲线 Diffie-Hellman),纯粹在Python,在 MIT 许可下发布。使用此库,您可以快速创建密钥对(签名密钥和验证密钥)、签署消息并验证签名。您还可以根据交换的公钥就共享密钥达成一致。密钥和签名非常短,使其易于处理和合并到其他协议中。

注意:此库不应在生产设置中使用,有关详细信息,请参阅安全性。

特征

该库为五个流行的 NIST“Suite B”GF(p)(素数字段)曲线提供密钥生成、签名、验证和共享秘密推导,密钥长度为 192、224、256、384 和 521 位。正如 OpenSSL 工具 ( ) 所知,这些曲线的“简称”openssl ecparam -list_curves是:prime192v1、 secp224r1、prime256v1、secp384r1和secp521r1。它包括比特币使用的 256 位曲线secp256k1。还支持从 160 到 512 位的 Brainpool 曲线的常规(非扭曲)变体。这些曲线的“简称”是:brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1. SEC 标准中的一些小曲线也包括在内(主要是为了加速库的测试),它们是: secp112r1, secp112r2,secp128r1, 和secp160r1. Ed25519 和 Ed448 曲线也支持密钥生成、签名和验证。不包括其他曲线,但在素数场上添加对更多曲线的支持并不难。

依赖项

该库仅使用 Python 和“六”包。它与 Python 2.6、2.7 和 3.3+ 兼容。它还支持在 pypy 和 pypy3 等替代实现上执行。

如果安装了gmpy2or gmpy,它们将用于更快的算术运算。安装此库后可以安装它们中的任何一个, python-ecdsa将在启动时检测它们的存在并自动使用它们。您应该更喜欢gmpy2Python3 以获得最佳性能。

要运行 OpenSSL 兼容性测试,“openssl”工具必须在您的 PATH. 此版本已针对 OpenSSL 0.9.8o、1.0.0a、1.0.2f、1.1.1d 和 3.0.1(以及其他)成功测试。

安装

该库在 PyPI 上可用,建议使用以下方式安装它pip:

pip install ecdsa

如果需要更高的性能并且使用本机代码不是问题,可以指定安装gmpy2:

pip install ecdsa[gmpy2]

或(较慢,遗留选项):

pip install ecdsa[gmpy] 速度

下表显示了该库生成密钥对keygen(. 所有这些值都以秒为单位。为方便起见,还提供了这些值的倒数:每秒可以生成多少密钥( ),每秒可以生成多少签名(),每秒可以验证多少签名(),可以共享多少秘密每秒导出 ( ),以及每秒可以验证多少个没有特定密钥预计算的签名 (signverifyecdhno PC verifykeygen/ssign/sverify/secdh/sno PC verify/s)。列中还提供了原始签名的大小(通常是签名可以编码的最小方式)siglen。用于tox -e speed在您自己的计算机上生成此表。在 Intel Core i7 4790K @ 4.0GHz 上,我得到以下性能:

siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s NIST192p: 48 0.00032s 3134.06 0.00033s 2985.53 0.00063s 1598.36 0.00129s 774.43 NIST224p: 56 0.00040s 2469.24 0.00042s 2367.88 0.00081s 1233.41 0.00170s 586.66 NIST256p: 64 0.00051s 1952.73 0.00054s 1867.80 0.00098s 1021.86 0.00212s 471.27 NIST384p: 96 0.00107s 935.92 0.00111s 904.23 0.00203s 491.77 0.00446s 224.00 NIST521p: 132 0.00210s 475.52 0.00215s 464.16 0.00398s 251.28 0.00874s 114.39 SECP256k1: 64 0.00052s 1921.54 0.00054s 1847.49 0.00105s 948.68 0.00210s 477.01 BRAINPOOLP160r1: 40 0.00025s 4003.88 0.00026s 3845.12 0.00053s 1893.93 0.00105s 949.92 BRAINPOOLP192r1: 48 0.00033s 3043.97 0.00034s 2975.98 0.00063s 1581.50 0.00135s 742.29 BRAINPOOLP224r1: 56 0.00041s 2436.44 0.00043s 2315.51 0.00078s 1278.49 0.00180s 556.16 BRAINPOOLP256r1: 64 0.00053s 1892.49 0.00054s 1846.24 0.00114s 875.64 0.00229s 437.25 BRAINPOOLP320r1: 80 0.00073s 1361.26 0.00076s 1309.25 0.00143s 699.29 0.00322s 310.49 BRAINPOOLP384r1: 96 0.00107s 931.29 0.00111s 901.80 0.00230s 434.19 0.00476s 210.20 BRAINPOOLP512r1: 128 0.00207s 483.41 0.00212s 471.42 0.00425s 235.43 0.00912s 109.61 SECP112r1: 28 0.00015s 6672.53 0.00016s 6440.34 0.00031s 3265.41 0.00056s 1774.20 SECP112r2: 28 0.00015s 6697.11 0.00015s 6479.98 0.00028s 3524.72 0.00058s 1716.16 SECP128r1: 32 0.00018s 5497.65 0.00019s 5272.89 0.00036s 2747.39 0.00072s 1396.16 SECP160r1: 42 0.00025s 3949.32 0.00026s 3894.45 0.00046s 2153.85 0.00102s 985.07 Ed25519: 64 0.00076s 1324.48 0.00042s 2405.01 0.00109s 918.05 0.00344s 290.50 Ed448: 114 0.00176s 569.53 0.00115s 870.94 0.00282s 355.04 0.01024s 97.69 ecdh ecdh/s NIST192p: 0.00104s 964.89 NIST224p: 0.00134s 748.63 NIST256p: 0.00170s 587.08 NIST384p: 0.00352s 283.90 NIST521p: 0.00717s 139.51 SECP256k1: 0.00154s 648.40 BRAINPOOLP160r1: 0.00082s 1220.70 BRAINPOOLP192r1: 0.00105s 956.75 BRAINPOOLP224r1: 0.00136s 734.52 BRAINPOOLP256r1: 0.00178s 563.32 BRAINPOOLP320r1: 0.00252s 397.23 BRAINPOOLP384r1: 0.00376s 266.27 BRAINPOOLP512r1: 0.00733s 136.35 SECP112r1: 0.00046s 2180.40 SECP112r2: 0.00045s 2229.14 SECP128r1: 0.00054s 1868.15 SECP160r1: 0.00080s 1243.98

要测试gmpy2加载时的性能,请使用tox -e speedgmpy2. 在同一台机器上,我得到以下性能gmpy2:

siglen keygen keygen/s sign sign/s verify verify/s no PC verify no PC verify/s NIST192p: 48 0.00017s 5933.40 0.00017s 5751.70 0.00032s 3125.28 0.00067s 1502.41 NIST224p: 56 0.00021s 4782.87 0.00022s 4610.05 0.00040s 2487.04 0.00089s 1126.90 NIST256p: 64 0.00023s 4263.98 0.00024s 4125.16 0.00045s 2200.88 0.00098s 1016.82 NIST384p: 96 0.00041s 2449.54 0.00042s 2399.96 0.00083s 1210.57 0.00172s 581.43 NIST521p: 132 0.00071s 1416.07 0.00072s 1389.81 0.00144s 692.93 0.00312s 320.40 SECP256k1: 64 0.00024s 4245.05 0.00024s 4122.09 0.00045s 2206.40 0.00094s 1068.32 BRAINPOOLP160r1: 40 0.00014s 6939.17 0.00015s 6681.55 0.00029s 3452.43 0.00057s 1769.81 BRAINPOOLP192r1: 48 0.00017s 5920.05 0.00017s 5774.36 0.00034s 2979.00 0.00069s 1453.19 BRAINPOOLP224r1: 56 0.00021s 4732.12 0.00022s 4622.65 0.00041s 2422.47 0.00087s 1149.87 BRAINPOOLP256r1: 64 0.00024s 4233.02 0.00024s 4115.20 0.00047s 2143.27 0.00098s 1015.60 BRAINPOOLP320r1: 80 0.00032s 3162.38 0.00032s 3077.62 0.00063s 1598.83 0.00136s 737.34 BRAINPOOLP384r1: 96 0.00041s 2436.88 0.00042s 2395.62 0.00083s 1202.68 0.00178s 562.85 BRAINPOOLP512r1: 128 0.00063s 1587.60 0.00064s 1558.83 0.00125s 799.96 0.00281s 355.83 SECP112r1: 28 0.00009s 11118.66 0.00009s 10775.48 0.00018s 5456.00 0.00033s 3020.83 SECP112r2: 28 0.00009s 11322.97 0.00009s 10857.71 0.00017s 5748.77 0.00032s 3094.28 SECP128r1: 32 0.00010s 10078.39 0.00010s 9665.27 0.00019s 5200.58 0.00036s 2760.88 SECP160r1: 42 0.00015s 6875.51 0.00015s 6647.35 0.00029s 3422.41 0.00057s 1768.35 Ed25519: 64 0.00030s 3322.56 0.00018s 5568.63 0.00046s 2165.35 0.00153s 654.02 Ed448: 114 0.00060s 1680.53 0.00039s 2567.40 0.00096s 1036.67 0.00350s 285.62 ecdh ecdh/s NIST192p: 0.00050s 1985.70 NIST224p: 0.00066s 1524.16 NIST256p: 0.00071s 1413.07 NIST384p: 0.00127s 788.89 NIST521p: 0.00230s 434.85 SECP256k1: 0.00071s 1409.95 BRAINPOOLP160r1: 0.00042s 2374.65 BRAINPOOLP192r1: 0.00051s 1960.01 BRAINPOOLP224r1: 0.00066s 1518.37 BRAINPOOLP256r1: 0.00071s 1399.90 BRAINPOOLP320r1: 0.00100s 997.21 BRAINPOOLP384r1: 0.00129s 777.51 BRAINPOOLP512r1: 0.00210s 475.99 SECP112r1: 0.00022s 4457.70 SECP112r2: 0.00024s 4252.33 SECP128r1: 0.00028s 3589.31 SECP160r1: 0.00043s 2305.02

(还有gmpy版本,使用执行它tox -e speedgmpy)

作为比较,高度优化的实现(包括某些曲线的曲线特定组合),如 OpenSSL 1.1.1d 中的实现,在同一台机器上提供以下性能数字。运行openssl speed ecdsa并openssl speed ecdh重现它:

sign verify sign/s verify/s 192 bits ecdsa (nistp192) 0.0002s 0.0002s 4785.6 5380.7 224 bits ecdsa (nistp224) 0.0000s 0.0001s 22475.6 9822.0 256 bits ecdsa (nistp256) 0.0000s 0.0001s 45069.6 14166.6 384 bits ecdsa (nistp384) 0.0008s 0.0006s 1265.6 1648.1 521 bits ecdsa (nistp521) 0.0003s 0.0005s 3753.1 1819.5 256 bits ecdsa (brainpoolP256r1) 0.0003s 0.0003s 2983.5 3333.2 384 bits ecdsa (brainpoolP384r1) 0.0008s 0.0007s 1258.8 1528.1 512 bits ecdsa (brainpoolP512r1) 0.0015s 0.0012s 675.1 860.1 sign verify sign/s verify/s 253 bits EdDSA (Ed25519) 0.0000s 0.0001s 28217.9 10897.7 456 bits EdDSA (Ed448) 0.0003s 0.0005s 3926.5 2147.7 op op/s 192 bits ecdh (nistp192) 0.0002s 4853.4 224 bits ecdh (nistp224) 0.0001s 15252.1 256 bits ecdh (nistp256) 0.0001s 18436.3 384 bits ecdh (nistp384) 0.0008s 1292.7 521 bits ecdh (nistp521) 0.0003s 2884.7 256 bits ecdh (brainpoolP256r1) 0.0003s 3066.5 384 bits ecdh (brainpoolP384r1) 0.0008s 1298.0 512 bits ecdh (brainpoolP512r1) 0.0014s 694.8

密钥和签名可以以不同的方式进行序列化(参见下面的用法)。对于 NIST192p 密钥,三种基本表示需要以下长度的字符串(以字节为单位):

to_string: signkey= 24, verifykey= 48, signature=48 compressed: signkey=n/a, verifykey= 25, signature=n/a DER: signkey=106, verifykey= 80, signature=55 PEM: signkey=278, verifykey=162, (no support for PEM signatures) 历史

2006 年,Peter Pearson 在 给 sci.crypt 的消息中宣布了他对 ECDSA 的纯 python 实现,可从他的下载站点获得。2010 年,Brian Warner 围绕此代码编写了一个包装器,以使其更易于使用且更安全。在 2020 年,Hubert Kario 包括了一个椭圆曲线密码学的实现,它在内部使用雅可比坐标,将性能提高了大约 20 倍。您正在查看此包装器的自述文件。

测试

要运行完整的测试套件,请执行以下操作:

tox -e coverage

在 Intel Core i7 4790K @ 4.0GHz 上,执行测试大约需要 18 秒。测试套件使用 hypothesis,因此测试套件执行时间存在一些固有的可变性。

通过运行“openssl”CLI 工具来检查与 OpenSSL 的兼容性的一部分,test_pyecdsa.py如果您想测试与它的兼容性(如果 OpenSSL 丢失、太旧或不支持上游版本,您将在上述运行中看到跳过的测试)。test_ecdh.pyPATHcoverage

安全

这个库的设计没有考虑到安全性。如果您正在处理需要保护的数据,我们建议您使用 OpenSSL 周围的质量包装器。pyca/cryptography就是这种包装器的一个例子。该库的主要用例是作为互操作性测试的可移植库和教学工具。

该库不能防止侧信道攻击。

不要让攻击者测量您生成密钥对或签署消息所需的时间。当密钥对生成或签名发生时,不允许攻击者在同一台物理机上运行代码(这包括虚拟机)。不要让攻击者在生成密钥对或签署消息时测量您的计算机使用了多少电量。不要让攻击者在生成密钥对或签署消息时测量来自您计算机的射频干扰。注意:仅加载私钥会导致密钥对生成。其他操作或攻击向量也可能容易受到攻击。对于一个老练的攻击者来说,只用私钥观察一个操作就足以完全重建私钥。

另请注意,任何 Pure-python 密码库都容易受到相同的侧信道攻击。这是因为 Python 不提供边信道安全原语(除了 hmac.compare_digest()),使得边信道安全编程成为不可能。

这个库依赖于一个强大的随机数来源。不要在os.urandom()不提供加密安全随机数的系统上使用它。

用法

您首先创建一个SigningKey. 您可以使用它对数据进行签名,方法是将数据作为字节字符串传入并取回签名(也是字节字符串)。你也可以要求aSigningKey给你相应的VerifyingKey。可VerifyingKey用于验证签名,通过将数据字符串和签名字节字符串传递给它:它返回 True 或 raises BadSignatureError。

from ecdsa import SigningKey sk = SigningKey.generate() # uses NIST192p vk = sk.verifying_key signature = sk.sign(b"message") assert vk.verify(signature, b"message")

每个SigningKey/VerifyingKey都与一条特定曲线相关联,例如 NIST192p(默认曲线)。更长的曲线更安全,但使用时间更长,并导致更长的密钥和签名。

from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key signature = sk.sign(b"message") assert vk.verify(signature, b"message")

SigningKey可以序列化为几种不同的格式:最短的是调用,s=sk.to_string()然后用 重新创建它 SigningKey.from_string(s, curve)。这种简短的形式不记录曲线,因此您必须确保传递到from_string()用于原始密钥的同一曲线。基于 NIST192p 的签名密钥的简短形式只有 24 个字节长。如果点编码无效或不在指定曲线上,from_string()将引发MalformedPointError.

from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) sk_string = sk.to_string() sk2 = SigningKey.from_string(sk_string, curve=NIST384p) print(sk_string.hex()) print(sk2.to_string().hex())

注意:虽然方法被称为to_string()它们返回的类型实际上是bytes,但“字符串”部分是 Python 2 遗留下来的。

sk.to_pem()并将sk.to_der()签名密钥序列化为 OpenSSL 使用的相同格式。PEM 文件看起来像熟悉的 ASCII 装甲 "-----BEGIN EC PRIVATE KEY-----"base64 编码格式,而 DER 格式是相同数据的较短二进制形式。 SigningKey.from_pem()/.from_der()将撤消此序列化。这些格式包括曲线名称,因此您不需要将曲线标识符传递给解串器。万一文件格式错误from_der() 并且from_pem()会引发UnexpectedDER或 MalformedPointError.

from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) sk_pem = sk.to_pem() sk2 = SigningKey.from_pem(sk_pem) # sk and sk2 are the same key

同样,VerifyingKey可以以相同的方式序列化: vk.to_string()/VerifyingKey.from_string()、to_pem()/from_pem()和 to_der()/from_der(). 需要相同的curve=参数 VerifyingKey.from_string()。

from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_string = vk.to_string() vk2 = VerifyingKey.from_string(vk_string, curve=NIST384p) # vk and vk2 are the same key from ecdsa import SigningKey, VerifyingKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk_pem = vk.to_pem() vk2 = VerifyingKey.from_pem(vk_pem) # vk and vk2 are the same key

有几种不同的方法来计算签名。从根本上说,ECDSA 接受一个代表被签名数据的数字,并返回一对代表签名的数字。and的hashfunc=参数 用于将任意字符串转换为固定长度的摘要,然后将其转换为 ECDSA 可以签名的数字,并且签名和验证都必须使用相同的方法。默认值为 ,但如果您使用 NIST256p 或更长的曲线,则可以 改为使用。sk.sign()vk.verify()hashlib.sha1hashlib.sha256

还有多种方式来表示签名。为了简单和最小的开销,默认值 sk.sign()和vk.verify()方法将其显示为一个短字符串。要使用不同的方案,请使用 sk.sign(sigencode=)andvk.verify(sigdecode=)参数。模块中有一些帮助函数在ecdsa.util这里很有用。

也可以SigningKey从确定性的“种子”创建一个。这可用于您希望从其他密钥派生一致签名密钥的协议中,例如,当您需要三个单独的密钥并且只想存储一个主密钥时。您应该从具有大约curve.baselen 字节熵的均匀分布的不可猜测种子开始,然后使用其中一个辅助函数ecdsa.util将其转换为正确范围内的整数,然后最后将其传递给SigningKey.from_secret_exponent(),如下所示:

import os from ecdsa import NIST384p, SigningKey from ecdsa.util import randrange_from_seed__trytryagain def make_key(seed): secexp = randrange_from_seed__trytryagain(seed, NIST384p.order) return SigningKey.from_secret_exponent(secexp, curve=NIST384p) seed = os.urandom(NIST384p.baselen) # or other starting point sk1a = make_key(seed) sk1b = make_key(seed) # note: sk1a and sk1b are the same key assert sk1a.to_string() == sk1b.to_string() sk2 = make_key(b"2-"+seed) # different key assert sk1a.to_string() != sk2.to_string()

如果应用程序将验证使用单个密钥生成的大量签名,则可以预先计算一些内部值以显着加快签名验证速度。收支平衡点出现在大约 100 个已验证的签名处。

要执行预计算,您可以在实例上调用该precompute()方法:VerifyingKey

from ecdsa import SigningKey, NIST384p sk = SigningKey.generate(curve=NIST384p) vk = sk.verifying_key vk.precompute() signature = sk.sign(b"message") assert vk.verify(signature, b"message")

一旦precompute()被调用,所有使用此密钥的签名验证将更快地执行。

OpenSSL 兼容性

要生成可由 OpenSSL 工具验证的签名,或验证由这些工具生成的签名,请使用:

# openssl ecparam -name prime256v1 -genkey -out sk.pem # openssl ec -in sk.pem -pubout -out vk.pem # echo "data for signing" > data # openssl dgst -sha256 -sign sk.pem -out data.sig data # openssl dgst -sha256 -verify vk.pem -signature data.sig data # openssl dgst -sha256 -prverify sk.pem -signature data.sig data import hashlib from ecdsa import SigningKey, VerifyingKey from ecdsa.util import sigencode_der, sigdecode_der with open("vk.pem") as f: vk = VerifyingKey.from_pem(f.read()) with open("data", "rb") as f: data = f.read() with open("data.sig", "rb") as f: signature = f.read() assert vk.verify(signature, data, hashlib.sha256, sigdecode=sigdecode_der) with open("sk.pem") as f: sk = SigningKey.from_pem(f.read(), hashlib.sha256) new_signature = sk.sign_deterministic(data, sigencode=sigencode_der) with open("data.sig2", "wb") as f: f.write(new_signature) # openssl dgst -sha256 -verify vk.pem -signature data.sig2 data

注意:如果需要兼容 OpenSSL 1.0.0 或更早版本, 可以使用sigencode_stringand sigdecode_stringfrom分别写入和读取签名。ecdsa.util

密钥也可以以 openssl 可以处理的格式编写:

from ecdsa import SigningKey, VerifyingKey with open("sk.pem") as f: sk = SigningKey.from_pem(f.read()) with open("sk.pem", "wb") as f: f.write(sk.to_pem()) with open("vk.pem") as f: vk = VerifyingKey.from_pem(f.read()) with open("vk.pem", "wb") as f: f.write(vk.to_pem()) 熵

创建签名密钥SigningKey.generate()需要某种形式的熵(与 from_secret_exponent/ from_string/ from_der/from_pem不同,后者是确定性的,不需要熵源)。默认源是os.urandom(),但您可以传递任何其他行为类似于参数os.urandom的entropy=函数来执行不同的操作。这在您希望获得可重复结果的单元测试中可能很有用。该 ecdsa.util.PRNG实用程序在这里很方便:它需要一个种子并从中产生一个强大的伪随机流:

from ecdsa.util import PRNG from ecdsa import SigningKey rng1 = PRNG(b"seed") sk1 = SigningKey.generate(entropy=rng1) rng2 = PRNG(b"seed") sk2 = SigningKey.generate(entropy=rng2) # sk1 and sk2 are the same key

同样,ECDSA 签名生成需要一个随机数,并且每个签名必须使用不同的数字(使用相同的数字两次将立即泄露私有签名密钥)。该sk.sign()方法接受一个 entropy=行为相同的参数SigningKey.generate(entropy=)。

确定性签名

如果您调用SigningKey.sign_deterministic(data)而不是.sign(data),代码将生成确定性签名而不是随机签名。这使用 RFC6979 中的算法安全地生成一个唯一k值,该值源自私钥和正在签名的消息。每次您使用相同的密钥签署相同的消息时,您将获得相同的签名(使用相同的k)。

这可能会成为未来版本的默认设置,因为它不易受到熵源故障的影响。

例子

创建 NIST192p 密钥对并立即将两者保存到磁盘:

from ecdsa import SigningKey sk = SigningKey.generate() vk = sk.verifying_key with open("private.pem", "wb") as f: f.write(sk.to_pem()) with open("public.pem", "wb") as f: f.write(vk.to_pem())

从磁盘加载签名密钥,使用它对消息进行签名(使用 SHA-1),然后将签名写入磁盘:

from ecdsa import SigningKey with open("private.pem") as f: sk = SigningKey.from_pem(f.read()) with open("message", "rb") as f: message = f.read() sig = sk.sign(message) with open("signature", "wb") as f: f.write(sig)

从磁盘加载验证密钥、消息和签名,并验证签名(假设 SHA-1 哈希):

from ecdsa import VerifyingKey, BadSignatureError vk = VerifyingKey.from_pem(open("public.pem").read()) with open("message", "rb") as f: message = f.read() with open("signature", "rb") as f: sig = f.read() try: vk.verify(sig, message) print "good signature" except BadSignatureError: print "BAD SIGNATURE"

创建 NIST521p 密钥对:

from ecdsa import SigningKey, NIST521p sk = SigningKey.generate(curve=NIST521p) vk = sk.verifying_key

从主种子创建三个独立的签名密钥:

from ecdsa import NIST192p, SigningKey from ecdsa.util import randrange_from_seed__trytryagain def make_key_from_seed(seed, curve=NIST192p): secexp = randrange_from_seed__trytryagain(seed, curve.order) return SigningKey.from_secret_exponent(secexp, curve) sk1 = make_key_from_seed("1:%s" % seed) sk2 = make_key_from_seed("2:%s" % seed) sk3 = make_key_from_seed("3:%s" % seed)

从磁盘加载验证密钥并使用未压缩和压缩格式(在 X9.62 和 SEC1 标准中定义)的十六进制编码打印它:

from ecdsa import VerifyingKey with open("public.pem") as f: vk = VerifyingKey.from_pem(f.read()) print("uncompressed: {0}".format(vk.to_string("uncompressed").hex())) print("compressed: {0}".format(vk.to_string("compressed").hex()))

从压缩格式的十六进制字符串加载验证密钥,输出未压缩:

from ecdsa import VerifyingKey, NIST256p comp_str = '022799c0d0ee09772fdd337d4f28dc155581951d07082fb19a38aa396b67e77759' vk = VerifyingKey.from_string(bytearray.fromhex(comp_str), curve=NIST256p) print(vk.to_string("uncompressed").hex())

与远程方的 ECDH 密钥交换:

from ecdsa import ECDH, NIST256p ecdh = ECDH(curve=NIST256p) ecdh.generate_private_key() local_public_key = ecdh.get_public_key() #send `local_public_key` to remote party and receive `remote_public_key` from remote party with open("remote_public_key.pem") as e: remote_public_key = e.read() ecdh.load_received_public_key_pem(remote_public_key) secret = ecdh.generate_sharedsecret_bytes()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3